﻿#include "MeasureView/ImageView.h"
#include <QPainter>
#include <QMouseEvent>
#include <QtMath>
#include <QGuiApplication>
#include <QDebug>
//#include "MeasureView/LensManager.h"
namespace Qly
{

Decoration::Decoration(ImageView *parent)
    :m_enable(false),
      m_pen(QBrush(Qt::red), 1, Qt::SolidLine),
      m_pImageView(parent)
{
}

void Decoration::setEnable(bool ena)
{
    m_enable = ena;
    if(m_pImageView)
    {
        m_pImageView->update();
    }
}

void Decoration::setPen(const QPen &pen)
{
    m_pen = pen;
    if(m_pImageView)
    {
        m_pImageView->update();
    }
}

void Decoration::setColor(const QColor &cl)
{
    m_pen.setColor(cl);
    if(m_pImageView)
    {
        m_pImageView->update();
    }
}

void Decoration::setLineWidth(int lineWidth)
{
    m_pen.setWidth(lineWidth);
    if(m_pImageView)
    {
        m_pImageView->update();
    }
}


Grid::Grid(ImageView *parent)
    :Decoration(parent)
{
    m_pen = QPen(QBrush(Qt::red), 1, Qt::DashDotLine);
}

void Grid::setLineStyle(Qt::PenStyle style)
{
    m_pen.setStyle(style);
    if(m_pImageView)
    {
        m_pImageView->update();
    }
}

void Grid::setGridSize(int width, int height)
{
    m_width = width;
    m_height = height;
    if(m_pImageView)
    {
        m_pImageView->update();
    }
}

void Grid::paint(QPainter &painter, int image_width, int image_height)
{
    if(!m_enable || m_width < 1 || m_height < 1) return;

    painter.save();
    painter.setPen(m_pen);

    for(int x = m_width; x < image_width; x += m_width) //先画竖线
    {
        painter.drawLine(x, 0, x, image_height);
    }

    for(int y = m_height; y < image_height; y += m_height)//再画横线
    {
        painter.drawLine(0, y, image_width, y);
    }

    painter.restore();
}

CenterCross::CenterCross(ImageView * parent)
:Decoration(parent)
{
    m_pen = QPen(QBrush(Qt::red), 1, Qt::SolidLine);
}

void CenterCross::setCrossSize(int width, int height)
{
    m_width = qBound(1, width, 10000);
    m_height = qBound(1, height, 10000);
    if(m_pImageView)
    {
        m_pImageView->update();
    }
}

void CenterCross::setRotate(double angle)
{
    m_angle = qBound(0.0, angle, 360.0);
    if(m_pImageView)
    {
        m_pImageView->update();
    }
}

void CenterCross::paint(QPainter &painter, int image_width, int image_height)
{
    if(!m_enable) return;

    int mid_x = image_width / 2;
    int mid_y = image_height / 2;

    painter.save();

    painter.translate(mid_x, mid_y);
    painter.rotate(m_angle);
    painter.setPen(m_pen);
    painter.drawLine(-m_width, 0, m_width, 0);
    painter.drawLine(0, -m_height, 0, m_height);

    painter.restore();
}

Ruler::Ruler(ImageView * parent)
    :Decoration(parent)
{
    m_pen = QPen(QBrush(Qt::red), 3, Qt::SolidLine);
    m_font = QFont(u8"宋体", 14, QFont::Bold);
}

void Ruler::setFont(const QFont &font)
{
    m_font = font;
    if(m_pImageView)
    {
        m_pImageView->update();
    }
}

void Ruler::setFontSize(int pointSize)
{
    m_font.setPointSize(pointSize);
    if(m_pImageView)
    {
        m_pImageView->update();
    }
}

void Ruler::setPosition(QPoint f)
{
    m_rulerOffsetX = f.x();
    m_rulerOffsetY = f.y();
    if(m_pImageView)
    {
        m_pImageView->update();
    }
}

void Ruler::setRuler(int length_pix, QString text)
{
    m_length_pix = length_pix;
    m_text = text;
    if(m_pImageView)
    {
        m_pImageView->update();
    }
}

void Ruler::paint(QPainter &painter, int image_width, int image_height)
{
    Q_UNUSED(image_width);
    Q_UNUSED(image_height);
    if( !m_enable  || m_length_pix < 5) //小于 5 个像素则直接退出
    {
        return;
    }
    painter.save();
    painter.setFont(m_font);
    painter.setPen(m_pen);
    int barLength = 5 + m_pen.width();
    int startX = m_rulerOffsetX - m_length_pix / 2.0;
    int endX = m_rulerOffsetX + m_length_pix / 2.0;
    painter.drawLine(QPoint(startX, m_rulerOffsetY), QPoint(endX, m_rulerOffsetY));
    painter.drawLine(QPoint(startX, m_rulerOffsetY - barLength), QPoint(startX, m_rulerOffsetY));
    painter.drawLine(QPoint(endX, m_rulerOffsetY - barLength), QPoint(endX, m_rulerOffsetY));

    QFontMetrics fm(m_font);
    QRect br = fm.boundingRect(m_text);
    painter.drawText(QPoint(m_rulerOffsetX - br.width() / 2.0, m_rulerOffsetY - m_pen.width()), m_text);
    painter.restore();
}

//void ImageView::setLens(int oldLensIndex, int newLensIndex)
//{
//    Q_UNUSED(oldLensIndex);
//    Q_UNUSED(newLensIndex);

//    if(m_lensManager)
//    {
//        double length_um = m_lensManager->currentLens().rulerLength_um;
//        double pixelSize_um = m_lensManager->currentLens().pixelSize_um;
//        if(pixelSize_um < 1e-3)
//        {
//            qWarning() << "pixelSize_um = " << pixelSize_um << " um, this maybe wrong!";
//            pixelSize_um = 1e-3;
//        }
//        double length_pix = length_um / pixelSize_um;
//        QString rulerText = m_lensManager->currentLens().rulerText;
//        m_ruler.setRuler(length_pix, rulerText);
//        update();
//    }
//}

ImageView::ImageView(QWidget *parent, int defaultX, int defaultY) :
        QWidget(parent),
        m_grid(this),
        m_cross(this),
        m_ruler(this),
        m_size(defaultX, defaultY),
        m_brush(Qt::gray, Qt::SolidPattern)
{
    m_decoSet.insert(&m_ruler);
    m_decoSet.insert(&m_cross);
    m_decoSet.insert(&m_grid);
    setFixedSize( m_size * m_zoomFactor);
    update();
}

//void ImageView::addLensManager(LensManager *p)
//{
//    m_lensManager = p;
//}

Grid &ImageView::grid()
{
    return m_grid;
}

CenterCross &ImageView::centerCross()
{
    return m_cross;
}

Ruler &ImageView::ruler()
{
    return m_ruler;
}

QSize ImageView::sizeHint() const
{
    return m_size * m_zoomFactor / 100.0;
}

QSize ImageView::imageSize()
{
    return m_size;
//    if(m_pImage)
//    {
//        return m_pImage->size();
//    }
//    return QSize();
}

void ImageView::setBrush(QBrush brush)
{
    m_brush= brush;
}

QImage ImageView::image(bool decorate)
{
    QImage image;
    if(m_pImage)
    {
        image = m_pImage->copy();
    }
    if(decorate)
    {
        QPainter painter(&image);
        painter.setRenderHint ( QPainter::Antialiasing, true );
        int w = image.width();
        int h = image.height();
        m_grid.paint(painter, w, h);
        m_cross.paint(painter, w, h);
    }
    return image;
}

bool ImageView::setImage(QImage &image)
{
    if(image.isNull()) return false;
    m_pImage = &image;
    m_size = m_pImage->size();
    setFixedSize( m_size * m_zoomFactor );
    update();
    return true;
}

bool ImageView::saveImage(QString fileName, bool decorate)
{
    if(!m_pImage || m_pImage->isNull())
    {
        return false;
    }
    QImage ima = image(decorate);
    return ima.save(fileName);
}

void ImageView::setZoomFactor(double factor)
{
    factor = qBound(0.01, factor, 10.0);
    factor = qRound(factor * 100.0) / 100.0; //取 2 位有效数字。
    if(m_zoomFactor != factor)
    {
        m_zoomFactor = factor;
        setFixedSize(m_size * m_zoomFactor);
        update();
        emit zoomFactorChanged(m_zoomFactor);
    }
}

void ImageView::setPixelSize(double oldPixelSize_um, double newPixelSize_um, int method)
{
    Q_UNUSED(oldPixelSize_um);
    Q_UNUSED(newPixelSize_um);
    Q_UNUSED(method);
//    if(m_lensManager)
//    {
//        double length_um = m_lensManager->currentLens().rulerLength_um;
//        double pixelSize_um = m_lensManager->currentLens().pixelSize_um;
//        if(pixelSize_um < 1e-3)
//        {
//            qWarning() << "pixelSize_um = " << pixelSize_um << " um, this maybe wrong!";
//            pixelSize_um = 1e-3;
//        }
//        double length_pix = length_um / pixelSize_um;
//        QString rulerText = m_lensManager->currentLens().rulerText;
//        m_ruler.setRuler(length_pix, rulerText);
//        update();
//    }
}


void ImageView::mouseMoveEvent(QMouseEvent *event)
{
    QWidget::mouseMoveEvent(event);
    double x = event->pos().x() - width() / 2.0;
    double y = event->pos().y() - height() / 2.0;
    QPointF point(x / m_zoomFactor, y / m_zoomFactor);
    emit mouseMoved(point);
}

void ImageView::mouseDoubleClickEvent(QMouseEvent *event)
{
    if(event->button() == Qt::LeftButton)
    {
        double x = event->pos().x() - width() / 2.0;
        double y = event->pos().y() - height() / 2.0;
        QPointF point(x / m_zoomFactor, y / m_zoomFactor);
        emit mouseDoubleClicked(point);
    }
    QWidget::mouseDoubleClickEvent(event);
}

void ImageView::enableWheelZoom(bool on)
{
    m_bWheelZoom = on;
}

void ImageView::wheelEvent(QWheelEvent *event)
{
    if(!m_bWheelZoom)
    {
        event->ignore();
        return;
    }
    bool isCtrlPressed = QGuiApplication::keyboardModifiers() & Qt::ControlModifier;
    bool isAltPressed = QGuiApplication::keyboardModifiers() & Qt::AltModifier;
    if(isCtrlPressed | isAltPressed)
    {
        event->ignore();
        return;
    }
    double scale = event->angleDelta().y() > 0 ? 1.05 : 0.95;

    double factor = m_zoomFactor * scale;
    setZoomFactor(factor);
}

void ImageView::drawImage(QPainter &painter)
{
    if(m_pImage)
    {
        painter.drawImage ( 0, 0, *m_pImage );
    }
    else
    {
        painter.setBrush(m_brush);
        painter.drawRect(QRect(0, 0, m_size.width(), m_size.height()));
    }
}

void ImageView::addDocoration(Decoration *pDeco)
{
    if(pDeco)
    {
        m_decoSet.insert(pDeco);
    }
}

void ImageView::removeDecoration(Decoration *pDeco)
{
    m_decoSet.remove(pDeco);
}

void ImageView::removeAllDecoration()
{
    m_decoSet.clear();
    m_decoSet.insert(&m_ruler);
    m_decoSet.insert(&m_cross);
    m_decoSet.insert(&m_grid);
}

void ImageView::paintEvent( QPaintEvent * event )
{
    (void) event;
    QPainter painter(this);
    painter.setRenderHint ( QPainter::Antialiasing, true );
    painter.scale(m_zoomFactor, m_zoomFactor);
    drawImage(painter);
    int w = m_size.width();
    int h = m_size.height();

    QSetIterator<Decoration *> iter(m_decoSet);
    while (iter.hasNext())
    {
        Decoration * p = iter.next();
        p->paint(painter, w, h);
    }
//    m_grid.paint(painter, w, h);
//    m_cross.paint(painter, w, h);
//    m_ruler.paint(painter, w, h);
}
}
